/**
 * @fileoverview Dx
 */

/**
 * setup Dx framework
 */
(function() {

   var D = { detected: {} };

   // detect non-enumerables
   var sampleObject = {};

   var isEnumerable = Object.prototype.propertyIsEnumerable;

   // non-enumerables that might not be detected in IE browsers
   var candidates = [
      'hasOwnProperty',
      'valueOf',
      'isPrototypeOf',
      'propertyIsEnumerable',
      'toLocaleString',
      'toString',
      'constructor'
   ];

   var l = candidates.length;
   
   var GLOBAL = this;

   var n, indexed, win;

   for (; l--;) {

      n = candidates[l];

      sampleObject[n] = 'n';

      if (isEnumerable.call(sampleObject, n)) {

         candidates.splice(l, 1);

      }

      delete sampleObject[n];

   }

   D.nonEnumerables = candidates;

   // expose Dx as global
   this.Dx = D;

   // global
   D.GLOBAL = GLOBAL;
   
   // detect if running on browser
   win = 'window' in GLOBAL ? GLOBAL.window : void(0);
   
   if (win && GLOBAL === win) {
      
      D.detected['browser'] = true;
      
   }
   
   win = null;

}).call(null);

/**
 * iterates the Object (target)
 * @param {*} target the Object to iterate
 * @param {Function} callback the callback Function to call for iterated items
 * @param {*} scope the scope of the callback Function when invoked.
 * @return {*} the target parameter
 */
Dx.each = function(target, callback, scope) {

   for (var n in target) {

      if (callback.call(scope, n, target[n], target) === false) {

         break;

      }

   }

   var O = Object.prototype;

   if (target instanceof O.constructor) {

      var enums = Dx.nonEnumerables;

      var hasOwn = O.hasOwnProperty;

      for (var n, l = enums.length; l--;) {

         n = enums[l];

         if (target[n] === O[n] && !hasOwn.call(target, n)) {

            continue;

         }

         if (callback.call(scope, n, target[n], target) === false) {

            break;

         }

      }

   }

   return target;

};

/**
 * Dx.clearObject callback
 * @this {*} target object
 * @param {String} name property name
 * @param {*} value new property value
 * @param {Object} source the source object iterated
 */
Dx._callback_clearObject = function(name, value, source) {

   delete source[name];

};

/**
 * clears the properties of an object
 * @param {Object} obj target object
 * @return {Object} the target object that has its properties cleared.
 */
Dx.clearObject = function(obj) {

   var D = Dx;

   D.each(obj, D._callback_clearObject);

   return obj;

};

/**
 * Dx.assign callback
 * @this {*} target object
 * @param {String} name property name
 * @param {*} value new property value
 * @param {Object} source the source object iterated
 */
Dx._callback_assign = function(name, value, source) {

   this[name] = value;

};


/**
 * Assign new properties to Object (target)
 * @param {*} target the target Object
 * @param {Object} properties the new properties to assign to the target Object
 * @param {Object=} defaults the defaults properties to assign to target
 *    before assigning the properties
 * @return {*} the target (Object)
 */
Dx.assign = function(target, properties, defaults) {

   var D = Dx,

      callback = D._callback_assign;

   if (defaults) {

      D.each(defaults, callback, target);

   }

   D.each(properties, callback, target);

   return target;

};

/**
 * Checks if o is Object
 * @param {*} o the subject
 * @param {Boolean=} checkIfNativeObject true if also check if o is
 *    a native Javascript Object. default is true.
 * @return {Boolean} true if o subject is an Object
 */
Dx.isObject = function(o, checkIfNativeObject) {

   var O = Object;

   var isNative = o instanceof O &&
         O.prototype.toString.call(o) == '[object Object]';

   return o != null && (

      checkIfNativeObject === false ?

         (isNative || typeof o == 'object') :

            isNative

   );


};

/**
 * Checks if o is String
 * @param {*} o the subject
 * @param {Boolean=} checkIfNotEmpty true if also check if o is
 *    a native Javascript Object
 * @return {Boolean} true if o subject is a String
 */
Dx.isString = function(o, checkIfNotEmpty) {

   return Object.prototype.toString.call(o) == '[object String]' &&

      (!checkIfNotEmpty || !!o);

};


/**
 * Checks if o is Boolean
 * @param {*} o the subject
 * @return {Boolean} true if o subject is a Boolean
 */
Dx.isBoolean = function(o) {

   return Object.prototype.toString.call(o) == '[object Boolean]';

};

/**
 * Checks if o is Number
 * @param {*} o the subject
 * @return {Boolean} true if o subject is a Number
 */
Dx.isNumber = function(o) {

   return Object.prototype.toString.call(o) == '[object Number]' && isFinite(o);

};

/**
 * Checks if o is Scalar or one of the following types:
 *    String, Number, or Boolean (if second parameter is true)
 * @param {*} o the subject
 * @param {Boolean=} includeBoolean if include Boolean as scalar type
 *    default is false
 * @return {Boolean} true if o subject is a Scalar
 */
Dx.isScalar = function(o, includeBoolean) {

   var type = Object.prototype.toString.call(o);

   return type == '[object String]' ||

      (type == '[object Number]' && isFinite(o)) ||

      (!!includeBoolean && type == '[object Boolean]');

};

/**
 * Checks if o is Function
 * @param {*} o the subject
 * @return {Boolean} true if o subject is a Function
 */
Dx.isFunction = function(o) {

   return Object.prototype.toString.call(o) == '[object Function]';

};

/**
 * Checks if o is Array
 * @param {*} o the subject
 * @param {Boolean=} checkIfNotEmpty include check if Array is not empty
 * @return {Boolean} true if o subject is an Array
 */
Dx.isArray = function(o, checkIfNotEmpty) {

   return Object.prototype.toString.call(o) == '[object Array]' &&

      (!checkIfNotEmpty || !!o.length);

};

/**
 * Checks if o is Date
 * @param {*} o the subject
 * @return {Boolean} true if o subject is a Date object
 */
Dx.isDate = function(o) {

   return Object.prototype.toString.call(o) == '[object Date]';

};

/**
 * Checks if o is Regex
 * @param {*} o the subject
 * @return {Boolean} true if o subject is a Regex object
 */
Dx.isRegExp = function(o) {

   return Object.prototype.toString.call(o) == '[object RegExp]';

};

/**
 * Checks if o is of type given the signature
 * @param {*} o the subject
 * @param {String} signature the type to check:
 *    Object, String, Number, Date, Regex
 * @return {Boolean} true if o subject is an object of type
 *    provided by signature parameter.
 */
Dx.isSignature = function(o, signature) {

   return !!signature &&

      Object.prototype.toString.call(o) == '[object ' + String(signature) + ']';

};

/**
 * Checks if property is enumerable in o
 * @param {String} property the property name to check if enumerable
 * @param {*} o the subject
 * @return {Boolean} true if o subject is an object of type
 *    provided by signature parameter.
 */
Dx.isPropertyEnumerable = function(property, o) {

   var Obj = Object;

   var O = Obj.prototype;

   // handle non-enumerable property
   return O.hasOwnProperty.call(o, property) || (

      o instanceof Obj ?

         (property in o && o[property] !== O[property]) :

         O.propertyIsEnumerable.call(o, property)

   );

};

/**
 * Creates an empty function named "Empty"
 * @return {Function} an empty function named "Empty"
 */
Dx.createEmptyFunction = function() {

   function empty() {};

   return empty;

};

/**
 * creates an uninitialized instance of a Class/Function
 * @param {Function} Class any instance of Function.
 * @return {Object} newly instantiated object from a given class
 */
Dx.createObject = function(Class) {

   var O = Object;

   var Temp;

   if (Class === O) {

      return new O();

   }

   Temp = arguments.callee.$emptyFunction;

   Temp.prototype = Class.prototype;

   return new Temp();

};

/**
 * an temporary empty function used only to instantiate a prototype Class
 */
Dx.createObject.$emptyFunction = Dx.createEmptyFunction();

